<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>录制数据播放器 - Recording Player</title>
    <style>
      * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
      }

      body {
        font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
        background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
        min-height: 100vh;
        padding: 20px;
      }

      .container {
        max-width: 1200px;
        margin: 0 auto;
        background: white;
        border-radius: 20px;
        box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
        overflow: hidden;
      }

      .header {
        background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
        color: white;
        padding: 30px;
        text-align: center;
      }

      .header h1 {
        font-size: 2.5em;
        margin-bottom: 10px;
        font-weight: 300;
      }

      .header p {
        font-size: 1.1em;
        opacity: 0.9;
      }

      .content {
        padding: 40px;
      }

      .section {
        margin-bottom: 40px;
        padding: 30px;
        background: #f8f9fa;
        border-radius: 15px;
        border-left: 5px solid #667eea;
      }

      .section h2 {
        color: #333;
        margin-bottom: 20px;
        font-size: 1.8em;
        font-weight: 500;
      }

      .file-upload {
        display: flex;
        flex-direction: column;
        align-items: center;
        gap: 20px;
        padding: 40px;
        border: 3px dashed #dee2e6;
        border-radius: 15px;
        background: #fff;
        transition: all 0.3s ease;
      }

      .file-upload.drag-over {
        border-color: #667eea;
        background: rgba(102, 126, 234, 0.1);
      }

      .file-input {
        display: none;
      }

      .btn {
        padding: 12px 24px;
        border: none;
        border-radius: 8px;
        cursor: pointer;
        font-size: 16px;
        font-weight: 500;
        transition: all 0.3s ease;
        display: flex;
        align-items: center;
        gap: 8px;
      }

      .btn:hover {
        transform: translateY(-2px);
        box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
      }

      .btn-primary {
        background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
        color: white;
      }

      .btn:disabled {
        opacity: 0.6;
        cursor: not-allowed;
        transform: none;
      }

      .icon {
        width: 16px;
        height: 16px;
      }

      .status {
        padding: 15px;
        border-radius: 8px;
        margin-bottom: 20px;
        font-weight: 500;
        background: #d1ecf1;
        color: #0c5460;
        border: 1px solid #bee5eb;
      }

      .player-container {
        margin-top: 20px;
        border: 2px solid #dee2e6;
        border-radius: 10px;
        overflow: hidden;
        background: #fff;
        display: none;
      }

      .player-target {
        width: 100%;
        height: 70vh;
        min-height: 400px;
        max-height: 800px;
        border: none;
        background: #f8f9fa;
        position: relative;
      }

      .player-target .rr-player {
        width: 100% !important;
        height: 100% !important;
      }

      .file-info {
        background: #e9ecef;
        padding: 15px;
        border-radius: 8px;
        margin-top: 15px;
        display: none;
      }

      .file-info h3 {
        margin-bottom: 10px;
        color: #495057;
      }

      .controls {
        display: flex;
        gap: 15px;
        margin-bottom: 20px;
        flex-wrap: wrap;
      }

      @media (max-width: 768px) {
        .controls {
          flex-direction: column;
        }

        .btn {
          justify-content: center;
        }

        .header h1 {
          font-size: 2em;
        }

        .content {
          padding: 20px;
        }
      }
    </style>
  </head>
  <script src="./rrweb/index.js"></script>

  <body>
    <div class="container">
      <div class="header">
        <h1>🎬 录制数据播放器</h1>
        <p>上传并播放rrweb录制的会话数据文件</p>
      </div>

      <div class="content">
        <!-- 文件上传区域 -->
        <div class="section">
          <h2>📁 文件上传</h2>
          <div class="status" id="uploadStatus">
            请选择或拖拽录制数据文件（JSON格式）
          </div>

          <div class="file-upload" id="fileUpload">
            <svg
              class="icon"
              style="width: 48px; height: 48px; color: #6c757d"
              fill="currentColor"
              viewBox="0 0 20 20"
            >
              <path
                fill-rule="evenodd"
                d="M3 17a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zM6.293 6.707a1 1 0 010-1.414l3-3a1 1 0 011.414 0l3 3a1 1 0 01-1.414 1.414L11 5.414V13a1 1 0 11-2 0V5.414L7.707 6.707a1 1 0 01-1.414 0z"
                clip-rule="evenodd"
              ></path>
            </svg>
            <p style="color: #6c757d; font-size: 18px; margin: 0">
              拖拽文件到此处或点击选择文件
            </p>
            <input
              type="file"
              id="fileInput"
              accept=".json"
              class="file-input"
            />
            <label for="fileInput" class="btn btn-primary">
              <svg class="icon" fill="currentColor" viewBox="0 0 20 20">
                <path
                  fill-rule="evenodd"
                  d="M3 17a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zM6.293 6.707a1 1 0 010-1.414l3-3a1 1 0 011.414 0l3 3a1 1 0 01-1.414 1.414L11 5.414V13a1 1 0 11-2 0V5.414L7.707 6.707a1 1 0 01-1.414 0z"
                  clip-rule="evenodd"
                ></path>
              </svg>
              选择文件
            </label>
          </div>

          <div class="file-info" id="fileInfo">
            <h3>文件信息</h3>
            <p>文件名: <span id="fileName">-</span></p>
            <p>事件数量: <span id="eventCount">-</span></p>
          </div>
        </div>

        <!-- 播放控制区域 -->
        <div class="section">
          <h2>🎥 播放控制</h2>
          <div class="status" id="playStatus">暂无数据 - 请先上传录制文件</div>

          <div class="controls">
            <button class="btn btn-primary" id="playBtn" disabled>
              <svg class="icon" fill="currentColor" viewBox="0 0 20 20">
                <path
                  fill-rule="evenodd"
                  d="M10 18a8 8 0 100-16 8 8 0 000 16zM9.555 7.168A1 1 0 008 8v4a1 1 0 001.555.832l3-2a1 1 0 000-1.664l-3-2z"
                  clip-rule="evenodd"
                ></path>
              </svg>
              开始播放
            </button>
          </div>

          <div class="player-container" id="playerContainer">
            <div id="playerTarget" class="player-target"></div>
          </div>
        </div>
      </div>
    </div>

    <!-- 引入rrweb库 -->
    <script src="./rrweb/rrweb.min.js"></script>
    <link rel="stylesheet" href="./rrweb/style.css" />

    <script>
      class RecordingPlayer {
        constructor() {
          this.recordingData = null
          this.player = null

          this.initializeElements()
          this.bindEvents()
        }

        initializeElements() {
          this.fileInput = document.getElementById('fileInput')
          this.fileUpload = document.getElementById('fileUpload')
          this.uploadStatus = document.getElementById('uploadStatus')
          this.playStatus = document.getElementById('playStatus')
          this.playBtn = document.getElementById('playBtn')
          this.playerContainer = document.getElementById('playerContainer')
          this.playerTarget = document.getElementById('playerTarget')
          this.fileInfo = document.getElementById('fileInfo')
          this.fileName = document.getElementById('fileName')
          this.eventCount = document.getElementById('eventCount')
        }

        bindEvents() {
          this.fileInput.addEventListener('change', (e) =>
            this.handleFileSelect(e)
          )
          this.playBtn.addEventListener('click', () => this.startPlayback())

          // 添加窗口大小变化监听
          window.addEventListener('resize', () => this.handleResize())

          // 拖拽事件
          this.fileUpload.addEventListener('dragover', (e) => {
            e.preventDefault()
            this.fileUpload.classList.add('drag-over')
          })

          this.fileUpload.addEventListener('dragleave', () => {
            this.fileUpload.classList.remove('drag-over')
          })

          this.fileUpload.addEventListener('drop', (e) => {
            e.preventDefault()
            this.fileUpload.classList.remove('drag-over')
            const files = e.dataTransfer.files
            if (files.length > 0) {
              this.loadFile(files[0])
            }
          })
        }

        handleFileSelect(event) {
          const file = event.target.files[0]
          if (file) {
            this.loadFile(file)
          }
        }

        async loadFile(file) {
          try {
            if (!file.name.endsWith('.json')) {
              throw new Error('请选择JSON格式的录制文件')
            }

            this.uploadStatus.textContent = '正在加载文件...'

            const text = await file.text()
            const data = JSON.parse(text)

            if (!data.events || !Array.isArray(data.events)) {
              throw new Error('文件格式不正确，缺少events数据')
            }

            this.recordingData = data
            this.updateFileInfo(file, data)
            this.updateUI('loaded')
          } catch (error) {
            console.error('文件加载失败:', error)
            alert(`文件加载失败：${error.message}`)
            this.updateUI('error')
          }
        }

        updateFileInfo(file, data) {
          this.fileName.textContent = file.name
          this.eventCount.textContent = data.events.length
          this.fileInfo.style.display = 'block'
        }

        startPlayback() {
          try {
            if (!this.recordingData) {
              throw new Error('没有可播放的数据')
            }

            // 清空之前的播放器
            this.playerTarget.innerHTML = ''

            // 先显示容器，确保能获取到正确的尺寸
            this.playerContainer.style.display = 'block'

            // 等待一帧后获取容器尺寸，确保DOM已经渲染
            requestAnimationFrame(() => {
              const containerRect = this.playerTarget.getBoundingClientRect()
              const containerWidth =
                containerRect.width || this.playerTarget.offsetWidth || 800
              const containerHeight = Math.max(
                containerRect.height || this.playerTarget.offsetHeight,
                600
              )

              console.log(
                'Container dimensions:',
                containerWidth,
                containerHeight
              )

              // 创建新的播放器
              this.player = new rrwebPlayer({
                target: this.playerTarget,
                props: {
                  events: this.recordingData.events,
                  width: containerWidth,
                  height: containerHeight - 100,
                  autoPlay: true,
                  speedOption: [0.5, 1, 2, 4, 8],
                  showController: true,
                  tags: {},
                  skipInactive: true,
                  showWarning: false,
                  UNSAFE_replayCanvas: true, // 启用canvas回放以支持视频和媒体内容
                  // 鼠标轨迹配置
                  mouseTail: {
                    duration: 500,
                    lineCap: 'round',
                    lineWidth: 3,
                    strokeStyle: 'red',
                  },
                  // 插入自定义样式规则以确保播放器正确显示
                  insertStyleRules: [
                    '.rr-player { width: 100% !important; height: 100% !important; }',
                    '.rr-player iframe { width: 100% !important; height: calc(100% - 40px) !important; }',
                  ],
                },
              })

              this.updateUI('playing')
            })
          } catch (error) {
            console.error('播放失败:', error)
            alert(`播放失败：${error.message}`)
            this.updateUI('error')
          }
        }

        handleResize() {
          // 防抖处理，避免频繁调整
          if (this.resizeTimeout) {
            clearTimeout(this.resizeTimeout)
          }

          this.resizeTimeout = setTimeout(() => {
            if (this.player && this.playerTarget) {
              const containerRect = this.playerTarget.getBoundingClientRect()
              const containerWidth =
                containerRect.width || this.playerTarget.offsetWidth
              const containerHeight = Math.max(
                containerRect.height || this.playerTarget.offsetHeight,
                400
              )

              // 重新创建播放器以适应新尺寸
              if (this.recordingData) {
                this.startPlayback()
              }
            }
          }, 300)
        }

        updateUI(state) {
          switch (state) {
            case 'loaded':
              this.uploadStatus.textContent = '✅ 文件加载成功 - 可以开始播放'
              this.playStatus.textContent = `📁 已加载 ${this.recordingData.events.length} 个事件 - 点击开始播放`
              this.playBtn.disabled = false
              break

            case 'playing':
              this.playStatus.textContent = '▶️ 正在播放录制内容...'
              break

            case 'error':
              this.uploadStatus.textContent = '❌ 文件加载失败 - 请检查文件格式'
              this.playStatus.textContent = '暂无数据 - 请先上传录制文件'
              this.playBtn.disabled = true
              this.fileInfo.style.display = 'none'
              break
          }
        }
      }

      // 页面加载完成后初始化播放器
      document.addEventListener('DOMContentLoaded', () => {
        try {
          window.recordingPlayer = new RecordingPlayer()
          console.log('录制播放器初始化成功')
        } catch (error) {
          console.error('播放器初始化失败:', error)
          alert('播放器初始化失败，请刷新页面重试')
        }
      })
    </script>
  </body>
</html>
